home *** CD-ROM | disk | FTP | other *** search
/ boe.pres.k12.wv.us / boe.pres.k12.wv.us.zip / boe.pres.k12.wv.us / Utilities / Xerox Workcentre 5335 / Windows Utilities / Font Management Utility / ChineseS / Xerox Font Management Utility.msi / Data1.cab / fmu.chm3 / skinsupport / madcapmerging.js < prev    next >
Text File  |  2011-04-21  |  46KB  |  1,952 lines

  1. /// <reference path="MadCapUtilities.js" />
  2.  
  3. // {{MadCap}} //////////////////////////////////////////////////////////////////
  4. // Copyright: MadCap Software, Inc - www.madcapsoftware.com ////////////////////
  5. ////////////////////////////////////////////////////////////////////////////////
  6. // <version>6.1.0.0</version>
  7. ////////////////////////////////////////////////////////////////////////////////
  8.  
  9. var gHelpSystem = null;
  10.  
  11. function FMCGetHelpSystem()
  12. {
  13.     if ( !gHelpSystem )
  14.     {
  15.         var pathToHelpSystem = FMCGetAttribute( document.documentElement, "MadCap:PathToHelpSystem" );
  16.         
  17.         if ( pathToHelpSystem == null )
  18.         {
  19.             pathToHelpSystem = "";
  20.         }
  21.         
  22.         var hsFileName = FMCGetAttribute( document.documentElement, "MadCap:HelpSystemFileName" );
  23.         var currentFolder = new CMCUrl( FMCEscapeHref( document.location.href ) ).ToFolder();
  24.         var absPathToHS = currentFolder.CombinePath( pathToHelpSystem );
  25.         var hsUrl = absPathToHS.AddFile( hsFileName );
  26.  
  27.         gHelpSystem = new CMCHelpSystem( null, absPathToHS.FullPath, hsUrl.FullPath, null, null );
  28.     }
  29.     
  30.     return gHelpSystem;
  31. }
  32.  
  33. /* -CatapultCompiler- -Begin- -Copy to CSH Javascript- */
  34.  
  35. //
  36. //    Class CMCHelpSystem
  37. //
  38.  
  39. function CMCHelpSystem( parentSubsystem, parentPath, xmlFile, tocPath, browseSequencePath )
  40. {
  41.     // Private member variables
  42.  
  43.     var mSelf                = this;
  44.     var mParentSubsystem    = parentSubsystem;
  45.     var mPath                = parentPath;
  46.     var mXmlFile            = xmlFile;
  47.     var mSubsystems            = new Array();
  48.     var mTocPath            = tocPath;
  49.     var mBrowseSequencePath    = browseSequencePath;
  50.     var mConceptMap            = null;
  51.     var mViewedConceptMap    = new CMCDictionary();
  52.     var mExists                = false;
  53.     var mAliasFile            = new CMCAliasFile( parentPath + "Data/Alias.xml", this );
  54.     var mTocFile            = new CMCTocFile( this, EMCTocType.Toc );
  55.     var mBrowseSequenceFile    = new CMCTocFile( this, EMCTocType.BrowseSequence );
  56.  
  57.     // Public properties
  58.  
  59.     this.TargetType                        = null;
  60.     this.SkinFolder                        = null;
  61.     this.SkinTemplateFolder                = null;
  62.     this.DefaultStartTopic                = null;
  63.     this.InPreviewMode                    = null;
  64.     this.LiveHelpOutputId                = null;
  65.     this.LiveHelpServer                    = null;
  66.     this.LiveHelpEnabled                = false;
  67.     this.IsWebHelpPlus                    = false;
  68.     this.ContentFolder                    = null;
  69.     this.UseCustomTopicFileExtension    = false;
  70.     this.CustomTopicFileExtension        = null;
  71.     this.PreloadImages                    = false;
  72.     
  73.     this.GlossaryUrl                    = null;
  74.  
  75.     // Constructor
  76.  
  77.     (function()
  78.     {
  79.         var xmlDoc    = CMCXmlParser.GetXmlDoc( xmlFile, false, null, null );
  80.         
  81.         mExists = xmlDoc != null;
  82.         
  83.         if ( !mExists )
  84.         {
  85.             return;
  86.         }
  87.  
  88.         if ( xmlDoc.getElementsByTagName( "Subsystems" ).length > 0 )
  89.         {
  90.             var urlNodes    = xmlDoc.getElementsByTagName( "Subsystems" )[0].getElementsByTagName( "Url" );
  91.             
  92.             for ( var i = 0; i < urlNodes.length; i++ )
  93.             {
  94.                 var urlNode    = urlNodes[i];
  95.                 var url        = urlNode.getAttribute( "Source" );
  96.                 var subPath    = url.substring( 0, url.lastIndexOf( "/" ) + 1 );
  97.                 var tocPath    = urlNode.getAttribute( "TocPath" );
  98.                 var browseSequencePath = urlNode.getAttribute( "BrowseSequencePath" );
  99.                 
  100.                 mSubsystems.push( new CMCHelpSystem( mSelf, mPath + subPath, mPath + url.substring( 0, url.lastIndexOf( "." ) ) + ".xml", tocPath, browseSequencePath ) );
  101.             }
  102.         }
  103.         
  104.         mSelf.TargetType = xmlDoc.documentElement.getAttribute( "TargetType" );
  105.         mSelf.SkinFolder = new CMCUrl( xmlDoc.documentElement.getAttribute( "Skin" ) ).ToFolder().FullPath;
  106.         mSelf.SkinTemplateFolder = xmlDoc.documentElement.getAttribute( "SkinTemplateFolder" );
  107.         mSelf.DefaultStartTopic = xmlDoc.documentElement.getAttribute( "DefaultUrl" );
  108.         mSelf.InPreviewMode = FMCGetAttributeBool( xmlDoc.documentElement, "InPreviewMode", false );
  109.         mSelf.LiveHelpOutputId = xmlDoc.documentElement.getAttribute( "LiveHelpOutputId" );
  110.         mSelf.LiveHelpServer = xmlDoc.documentElement.getAttribute( "LiveHelpServer" );
  111.         mSelf.LiveHelpEnabled = mSelf.LiveHelpOutputId != null;
  112.         mSelf.IsWebHelpPlus = mSelf.TargetType == "WebHelpPlus" && document.location.protocol.StartsWith( "http", false );
  113.         
  114.         var moveOutputContentToRoot    = FMCGetAttributeBool( xmlDoc.documentElement, "MoveOutputContentToRoot", false );
  115.         var makeFileLowerCase        = FMCGetAttributeBool( xmlDoc.documentElement, "MakeFileLowerCase", false );
  116.         var contentFolder            = "";
  117.         
  118.         if ( !moveOutputContentToRoot )
  119.         {
  120.             contentFolder = "Content/";
  121.         }
  122.         
  123.         if ( makeFileLowerCase )
  124.         {
  125.             contentFolder = contentFolder.toLowerCase();
  126.         }
  127.         
  128.         mSelf.ContentFolder = contentFolder;
  129.         mSelf.UseCustomTopicFileExtension = FMCGetAttributeBool( xmlDoc.documentElement, "UseCustomTopicFileExtension", false );
  130.         mSelf.CustomTopicFileExtension = FMCGetAttribute( xmlDoc.documentElement, "CustomTopicFileExtension" );
  131.         mSelf.PreloadImages = FMCGetAttributeBool( xmlDoc.documentElement, "PreloadImages", false );
  132.  
  133.         mSelf.GlossaryUrl = GetGlossaryUrl( xmlDoc );
  134.     })();
  135.  
  136.     // Public member functions
  137.     
  138.     this.GetExists      = function()
  139.     {
  140.         return mExists;
  141.     };
  142.     
  143.     this.GetParentSubsystem = function()
  144.     {
  145.         return mParentSubsystem;
  146.     };
  147.     
  148.     this.GetPath        = function()
  149.     {
  150.         return mPath;
  151.     };
  152.     
  153.     this.GetTocPath     = function( tocType )
  154.     {
  155.         return tocType == "toc" ? mTocPath : mBrowseSequencePath;
  156.     };
  157.     
  158.     this.GetFullTocPath = function( tocType, href )
  159.     {
  160.         var subsystem = this.GetHelpSystem( href );
  161.         var fullTocPath = new Object();
  162.  
  163.         fullTocPath.tocPath = this.GetTocPath( tocType );
  164.         subsystem.ComputeTocPath( tocType, fullTocPath );
  165.         
  166.         return fullTocPath.tocPath;
  167.     };
  168.     
  169.     this.ComputeTocPath = function( tocType, tocPath )
  170.     {
  171.         if ( mParentSubsystem )
  172.         {
  173.             var hsTocPath = this.GetTocPath( tocType );
  174.             
  175.             if ( !String.IsNullOrEmpty( hsTocPath ) )
  176.             {
  177.                 tocPath.tocPath = tocPath.tocPath ? hsTocPath + "|" + tocPath.tocPath : hsTocPath;
  178.             }
  179.             
  180.             mParentSubsystem.ComputeTocPath( tocType, tocPath );
  181.         }
  182.     };
  183.     
  184.     this.GetHelpSystem  = function( path )
  185.     {
  186.         var helpSystem    = null;
  187.         
  188.         for ( var i = 0; i < mSubsystems.length; i++ )
  189.         {
  190.             helpSystem = mSubsystems[i].GetHelpSystem( path );
  191.             
  192.             if ( helpSystem != null )
  193.             {
  194.                 return helpSystem;
  195.             }
  196.         }
  197.         
  198.         if ( path.StartsWith( mPath, false ) )
  199.         {
  200.             return this;
  201.         }
  202.         
  203.         return null;
  204.     };
  205.     
  206.     this.GetSubsystem   = function( id )
  207.     {
  208.         return mSubsystems[id];
  209.     };
  210.     
  211.     this.GetMergedAliasIDs    = function()
  212.     {
  213.         var ids    = mAliasFile.GetIDs();
  214.         
  215.         for ( var i = 0, length = mSubsystems.length; i < length; i++ )
  216.         {
  217.             var subsystem    = mSubsystems[i];
  218.             var subIDs        = subsystem.GetMergedAliasIDs();
  219.             
  220.             for ( var j = 0, length2 = subIDs.length; j < length2; j++ )
  221.             {
  222.                 ids[ids.length] = subIDs[j];
  223.             }
  224.         }
  225.         
  226.         return ids;
  227.     };
  228.     
  229.     this.GetMergedAliasNames    = function()
  230.     {
  231.         var names    = mAliasFile.GetNames();
  232.         
  233.         for ( var i = 0, length = mSubsystems.length; i < length; i++ )
  234.         {
  235.             var subsystem    = mSubsystems[i];
  236.             var subNames    = subsystem.GetMergedAliasNames();
  237.             
  238.             for ( var j = 0, length2 = subNames.length; j < length2; j++ )
  239.             {
  240.                 names[names.length] = subNames[j];
  241.             }
  242.         }
  243.         
  244.         return names;
  245.     };
  246.     
  247.     this.LookupCSHID    = function( id )
  248.     {
  249.         var idInfo    = mAliasFile.LookupID( id );
  250.  
  251.         if ( !idInfo.Found )
  252.         {
  253.             var subIDInfo    = null;
  254.             
  255.             for ( var i = 0; i < mSubsystems.length; i++ )
  256.             {
  257.                 var subsystem    = mSubsystems[i];
  258.                 
  259.                 subIDInfo = subsystem.LookupCSHID( id );
  260.                 
  261.                 if ( subIDInfo.Found )
  262.                 {
  263.                     idInfo = subIDInfo;
  264.                     
  265.                     var myPathUrl    = new CMCUrl( this.GetPath() );
  266.                     var subPathUrl    = new CMCUrl( subsystem.GetPath() );
  267.                     var relUrl        = subPathUrl.ToRelative( myPathUrl );
  268.                     
  269.                     idInfo.Topic = relUrl.FullPath + idInfo.Topic;
  270.                     
  271.                     break;
  272.                 }
  273.             }
  274.         }
  275.         
  276.         return idInfo;
  277.     };
  278.     
  279.     this.GetTocFile = function()
  280.     {
  281.         return mTocFile;
  282.     };
  283.     
  284.     this.GetBrowseSequenceFile = function()
  285.     {
  286.         return mBrowseSequenceFile;
  287.     };
  288.     
  289.     this.GetIndex       = function( onCompleteFunc, onCompleteArgs )
  290.     {
  291.         if ( !this.IsWebHelpPlus )
  292.         {
  293.             var xmlDoc        = LoadFirstIndex();
  294.             var preMerged    = FMCGetAttributeBool( xmlDoc.documentElement, "PreMerged", false );
  295.             
  296.             if ( !preMerged && mSubsystems.length != 0 )
  297.             {
  298.                 xmlDoc = LoadEntireIndex();
  299.                 
  300.                 for ( var i = 0; i < mSubsystems.length; i++ )
  301.                 {
  302.                     var subsystem    = mSubsystems[i];
  303.                     
  304.                     if ( !subsystem.GetExists() )
  305.                     {
  306.                         continue;
  307.                     }
  308.                     
  309.                     var xmlDoc2    = subsystem.GetMergedIndex();
  310.                     
  311.                     MergeIndexEntries( xmlDoc.getElementsByTagName( "IndexEntry" )[0], xmlDoc2.getElementsByTagName( "IndexEntry" )[0] );
  312.                 }
  313.             }
  314.             
  315.             onCompleteFunc( xmlDoc, onCompleteArgs );
  316.         }
  317.         else
  318.         {
  319.             function OnGetIndexComplete( xmlDoc, args )
  320.             {
  321.                 onCompleteFunc( xmlDoc, onCompleteArgs );
  322.             }
  323.  
  324.             var xmlDoc    = CMCXmlParser.CallWebService( MCGlobals.RootFolder + "Service/Service.asmx/GetIndex", true, OnGetIndexComplete, null );
  325.         }
  326.     };
  327.     
  328.     this.GetMergedIndex = function()
  329.     {
  330.         var xmlDoc  = LoadEntireIndex();
  331.         
  332.         for ( var i = 0; i < mSubsystems.length; i++ )
  333.         {
  334.             var subsystem   = mSubsystems[i];
  335.             
  336.             if ( !subsystem.GetExists() )
  337.             {
  338.                 continue;
  339.             }
  340.             
  341.             var xmlDoc2 = subsystem.GetMergedIndex();
  342.             
  343.             MergeIndexEntries( xmlDoc.getElementsByTagName( "IndexEntry" )[0], xmlDoc2.getElementsByTagName( "IndexEntry" )[0] );
  344.         }
  345.         
  346.         return xmlDoc;
  347.     };
  348.     
  349.     this.HasBrowseSequences    = function()
  350.     {
  351.         var xmlFile    = mXmlFile.substring( 0, mXmlFile.lastIndexOf( "." ) ) + ".xml";
  352.         var xmlDoc    = CMCXmlParser.GetXmlDoc( xmlFile, false, null, null );
  353.         
  354.         return xmlDoc.documentElement.getAttribute( "BrowseSequence" ) != null;
  355.     };
  356.     
  357.     this.HasToc                = function()
  358.     {
  359.         var xmlFile    = mXmlFile.substring( 0, mXmlFile.lastIndexOf( "." ) ) + ".xml";
  360.         var xmlDoc    = CMCXmlParser.GetXmlDoc( xmlFile, false, null, null );
  361.         
  362.         return xmlDoc.documentElement.getAttribute( "Toc" ) != null;
  363.     };
  364.     
  365.     this.IsMerged       = function()
  366.     {
  367.         return (mSubsystems.length > 0);
  368.     };
  369.     
  370.     this.GetConceptsLinks    = function( conceptTerms, callbackFunc, callbackArgs )
  371.     {
  372.         if ( this.IsWebHelpPlus )
  373.         {
  374.             function OnGetTopicsForConceptsComplete( xmlDoc, args )
  375.             {
  376.                 var links        = new Array();
  377.                 var nodes        = xmlDoc.documentElement.getElementsByTagName( "Url" );
  378.                 var nodeLength    = nodes.length;
  379.                 
  380.                 for ( var i = 0; i < nodeLength; i++ )
  381.                 {
  382.                     var node    = nodes[i];
  383.                     var title    = node.getAttribute( "Title" );
  384.                     var url        = node.getAttribute( "Source" );
  385.                     
  386.                     url = mPath + ((url.charAt( 0 ) == "/") ? url.substring( 1, url.length ) : url);
  387.                     
  388.                     links[links.length] = title + "|" + url;
  389.                 }
  390.                 
  391.                 callbackFunc( links, callbackArgs );
  392.             }
  393.             
  394.             var xmlDoc    = CMCXmlParser.CallWebService( MCGlobals.RootFolder + "Service/Service.asmx/GetTopicsForConcepts?Concepts=" + conceptTerms, true, OnGetTopicsForConceptsComplete, null );
  395.         }
  396.         else
  397.         {
  398.             var links    = null;
  399.  
  400.             conceptTerms = conceptTerms.replace( "\\;", "%%%%%" );
  401.             
  402.             if ( conceptTerms == "" )
  403.             {
  404.                 links = new Array();
  405.                 callbackFunc( links, callbackArgs );
  406.             }
  407.             
  408.             var concepts    = conceptTerms.split( ";" );
  409.             
  410.             links = this.GetConceptsLinksLocal( concepts );
  411.             
  412.             callbackFunc( links, callbackArgs );
  413.         }
  414.     };
  415.         
  416.     this.GetConceptsLinksLocal    = function( concepts )
  417.     {
  418.         var links    = new Array();
  419.         
  420.         for ( var i = 0; i < concepts.length; i++ )
  421.         {
  422.             var concept    = concepts[i];
  423.             
  424.             concept = concept.replace( "%%%%%", ";" );
  425.             concept = concept.toLowerCase();
  426.             
  427.             var currLinks    = this.GetConceptLinksLocal( concept );
  428.             
  429.             for ( var j = 0; j < currLinks.length; j++ )
  430.             {
  431.                 links[links.length] = currLinks[j];
  432.             }
  433.         }
  434.         
  435.         return links;
  436.     };
  437.     
  438.     this.GetConceptLinksLocal    = function( concept )
  439.     {
  440.         LoadConcepts();
  441.         
  442.         var links    = mViewedConceptMap.GetItem( concept );
  443.             
  444.         if ( !links )
  445.         {
  446.             links = mConceptMap.GetItem( concept );
  447.             
  448.             if ( !links )
  449.             {
  450.                 links = new Array( 0 );
  451.             }
  452.             
  453.             for ( var i = 0; i < mSubsystems.length; i++ )
  454.             {
  455.                 var subsystem   = mSubsystems[i];
  456.                 
  457.                 if ( !subsystem.GetExists() )
  458.                 {
  459.                     continue;
  460.                 }
  461.                 
  462.                 MergeConceptLinks( links, subsystem.GetConceptLinksLocal( concept ) );
  463.             }
  464.  
  465.             mViewedConceptMap.Add( concept, links );
  466.         }
  467.         
  468.         return links;
  469.     };
  470.     
  471.     this.LoadGlossary   = function( onCompleteFunc, onCompleteArgs )
  472.     {
  473.         if ( !this.IsWebHelpPlus )
  474.         {
  475.             if ( !this.IsMerged() )
  476.             {
  477.                 return;
  478.             }
  479.             
  480.             var xmlDoc    = this.GetGlossary();
  481.             
  482.             onCompleteFunc( xmlDoc, onCompleteArgs );
  483.         }
  484.         else
  485.         {
  486.             function OnGetGlossaryComplete( xmlDoc, args )
  487.             {
  488.                 onCompleteFunc( xmlDoc, onCompleteArgs );
  489.             }
  490.  
  491.             var xmlDoc    = CMCXmlParser.CallWebService( MCGlobals.RootFolder + "Service/Service.asmx/GetGlossary", true, OnGetGlossaryComplete, null );
  492.         }
  493.     }
  494.     
  495.     this.GetGlossary    = function()
  496.     {
  497.         var xmlDoc    = CMCXmlParser.GetXmlDoc( this.GlossaryUrl, false, null, null );
  498.         
  499.         for ( var i = 0; i < mSubsystems.length; i++ )
  500.         {
  501.             var subsystem   = mSubsystems[i];
  502.             
  503.             if ( !subsystem.GetExists() )
  504.             {
  505.                 continue;
  506.             }
  507.             
  508.             MergeGlossaries( xmlDoc, subsystem );
  509.         }
  510.         
  511.         return xmlDoc;
  512.     };
  513.     
  514.     this.GetSearchDBs   = function()
  515.     {
  516.         var searchDBs    = new Array();
  517.         var rootFrame    = FMCGetRootFrame();
  518.         var xmlDoc      = CMCXmlParser.GetXmlDoc( mPath + "Data/Search.xml", false, null, null );
  519.         var preMerged    = FMCGetAttributeBool( xmlDoc.documentElement, "PreMerged", false );
  520.  
  521.         searchDBs[searchDBs.length] = new rootFrame.frames["navigation"].frames["search"].CMCSearchDB( "Data/Search.xml", this );
  522.         
  523.         if ( !preMerged )
  524.         {
  525.             for ( var i = 0; i < mSubsystems.length; i++ )
  526.             {
  527.                 var subsystem   = mSubsystems[i];
  528.                 
  529.                 if ( !subsystem.GetExists() )
  530.                 {
  531.                     continue;
  532.                 }
  533.                 
  534.                 var searchDBs2  = subsystem.GetSearchDBs();
  535.                 
  536.                 for ( var j = 0; j < searchDBs2.length; j++ )
  537.                 {
  538.                     searchDBs[searchDBs.length] = searchDBs2[j];
  539.                 }
  540.             }
  541.         }
  542.         
  543.         return searchDBs;
  544.     };
  545.     
  546.     this.AdvanceTopic = function( tocType, moveType, tocPath, href )
  547.     {
  548.         var file = null;
  549.         
  550.         if ( tocType == "toc" )
  551.         {
  552.             file = mTocFile;
  553.         }
  554.         else if ( tocType == "browsesequences" )
  555.         {
  556.             file = mBrowseSequenceFile;
  557.         }
  558.         
  559.         file.AdvanceTopic( moveType, tocPath, href );
  560.     };
  561.     
  562.     // Private member functions
  563.     
  564.     function GetGlossaryUrl( xmlDoc )
  565.     {
  566.         var glossaryUrlRel = xmlDoc.documentElement.getAttribute( "Glossary" );
  567.         
  568.         if ( glossaryUrlRel == null )
  569.         {
  570.             return null;
  571.         }
  572.         
  573.         var pos = glossaryUrlRel.lastIndexOf( "." );
  574.         
  575.         glossaryUrlRel = glossaryUrlRel.substring( 0, pos + 1 ) + "xml";
  576.         
  577.         return mPath + glossaryUrlRel;
  578.     }
  579.     
  580.     function LoadFirstIndex()
  581.     {
  582.         var xmlDoc    = CMCXmlParser.GetXmlDoc( mPath + "Data/Index.xml", false, null, null );
  583.         
  584.         return xmlDoc;
  585.     }
  586.     
  587.     function LoadEntireIndex()
  588.     {
  589.         var xmlDoc      = LoadFirstIndex();
  590.         var head        = xmlDoc.documentElement;
  591.         var chunkNodes  = xmlDoc.getElementsByTagName( "Chunk" );
  592.         
  593.         if ( chunkNodes.length > 0 )
  594.         {
  595.             // Remove all attributes except "Count"
  596.             
  597.             var attributesClone = head.cloneNode( false ).attributes;
  598.             
  599.             for ( var i = 0; i < attributesClone.length; i++ )
  600.             {
  601.                 if ( attributesClone[i].nodeName != "Count" && attributesClone[i].nodeName != "count" )
  602.                 {
  603.                     head.removeAttribute( attributesClone[i].nodeName );
  604.                 }
  605.             }
  606.             
  607.             // Merge all chunks
  608.             
  609.             for ( var i = 0; i < chunkNodes.length; i++ )
  610.             {
  611.                 var xmlDoc2 = CMCXmlParser.GetXmlDoc( mPath + "Data/" + FMCGetAttribute( chunkNodes[i], "Link" ), false, null, null );
  612.                 
  613.                 MergeIndexEntries( xmlDoc.getElementsByTagName( "IndexEntry" )[0], xmlDoc2.getElementsByTagName( "IndexEntry" )[0] );
  614.             }
  615.             
  616.             head.removeChild( chunkNodes[0].parentNode );
  617.         }
  618.         
  619.         // Make links absolute
  620.         
  621.         for ( var i = 0; i < xmlDoc.documentElement.childNodes.length; i++ )
  622.         {
  623.             if ( xmlDoc.documentElement.childNodes[i].nodeName == "IndexEntry" )
  624.             {
  625.                 ConvertIndexLinksToAbsolute( xmlDoc.documentElement.childNodes[i] );
  626.                 
  627.                 break;
  628.             }
  629.         }
  630.         
  631.         //
  632.         
  633.         return xmlDoc;
  634.     }
  635.     
  636.     function MergeIndexEntries( indexEntry1, indexEntry2 )
  637.     {
  638.         var xmlDoc1     = indexEntry1.ownerDocument;
  639.         var entries1    = indexEntry1.getElementsByTagName( "Entries" )[0];
  640.         var entries2    = indexEntry2.getElementsByTagName( "Entries" )[0];
  641.         var entries     = xmlDoc1.createElement( "IndexEntry" ).appendChild( xmlDoc1.createElement( "Entries" ) );
  642.         
  643.         if ( entries1.getElementsByTagName( "IndexEntry" ).length == 0 )
  644.         {
  645.             if ( typeof( xmlDoc1.importNode ) == "function" )
  646.             {
  647.                 entries = xmlDoc1.importNode( entries2, true );
  648.             }
  649.             else
  650.             {
  651.                 entries = entries2.cloneNode( true );
  652.             }
  653.         }
  654.         else if ( entries2.getElementsByTagName( "IndexEntry" ).length == 0 )
  655.         {
  656.             entries = entries1.cloneNode( true );
  657.         }
  658.         else
  659.         {
  660.             for ( var i = 0, j = 0; i < entries1.childNodes.length && j < entries2.childNodes.length; )
  661.             {
  662.                 var currIndexEntry1 = entries1.childNodes[i];
  663.                 var currIndexEntry2 = entries2.childNodes[j];
  664.                 
  665.                 if ( currIndexEntry1.nodeType != 1 )
  666.                 {
  667.                     i++;
  668.                     continue;
  669.                 }
  670.                 else if ( currIndexEntry2.nodeType != 1 )
  671.                 {
  672.                     j++;
  673.                     continue;
  674.                 }
  675.                 
  676.                 var term1    = FMCGetAttribute( currIndexEntry1, "Term" ).toLowerCase();
  677.                 var term2    = FMCGetAttribute( currIndexEntry2, "Term" ).toLowerCase();
  678.                 
  679.                 if ( term1 == term2 )
  680.                 {
  681.                     MergeIndexEntries( currIndexEntry1, currIndexEntry2 );
  682.                     
  683.                     var links1      = FMCGetChildNodesByTagName( currIndexEntry1, "Links" )[0];
  684.                     var indexLinks2 = FMCGetChildNodesByTagName( currIndexEntry2, "Links" )[0].getElementsByTagName( "IndexLink" );
  685.                     
  686.                     for ( var k = 0; k < indexLinks2.length; k++ )
  687.                     {
  688.                         if ( typeof( xmlDoc1.importNode ) == "function" )
  689.                         {
  690.                             links1.appendChild( xmlDoc1.importNode( indexLinks2[k], true ) );
  691.                         }
  692.                         else
  693.                         {
  694.                             links1.appendChild( indexLinks2[k].cloneNode( true ) );
  695.                         }
  696.                     }
  697.                     
  698.                     entries.appendChild( currIndexEntry1.cloneNode( true ) );
  699.                     i++;
  700.                     j++;
  701.                 }
  702.                 else if ( term1 > term2 )
  703.                 {
  704.                     if ( typeof( xmlDoc1.importNode ) == "function" )
  705.                     {
  706.                         entries.appendChild( xmlDoc1.importNode( currIndexEntry2, true ) );
  707.                     }
  708.                     else
  709.                     {
  710.                         entries.appendChild( currIndexEntry2.cloneNode( true ) );
  711.                     }
  712.                     
  713.                     j++;
  714.                 }
  715.                 else
  716.                 {
  717.                     entries.appendChild( currIndexEntry1.cloneNode( true ) );
  718.                     i++;
  719.                 }
  720.             }
  721.             
  722.             // Append remaining nodes. There should never be a case where BOTH entries1 AND entries2 have remaining nodes.
  723.             
  724.             for ( ; i < entries1.childNodes.length; i++ )
  725.             {
  726.                 entries.appendChild( entries1.childNodes[i].cloneNode( true ) );
  727.             }
  728.             
  729.             for ( ; j < entries2.childNodes.length; j++ )
  730.             {
  731.                 if ( typeof( xmlDoc1.importNode ) == "function" )
  732.                 {
  733.                     entries.appendChild( xmlDoc1.importNode( entries2.childNodes[j], true ) );
  734.                 }
  735.                 else
  736.                 {
  737.                     entries.appendChild( entries2.childNodes[j].cloneNode( true ) );
  738.                 }
  739.             }
  740.         }
  741.         
  742.         indexEntry1.replaceChild( entries, entries1 );
  743.     }
  744.     
  745.     function ConvertGlossaryPageEntryToAbsolute( glossaryPageEntry, path )
  746.     {
  747.         var entryNode    = glossaryPageEntry.getElementsByTagName( "a" )[0];
  748.         var href        = FMCGetAttribute( entryNode, "href" );
  749.  
  750.         entryNode.setAttribute( "href", path + href );
  751.     }
  752.     
  753.     function ConvertIndexLinksToAbsolute( indexEntry )
  754.     {
  755.         for ( var i = 0; i < indexEntry.childNodes.length; i++ )
  756.         {
  757.             var currNode    = indexEntry.childNodes[i];
  758.             
  759.             if ( currNode.nodeName == "Entries" )
  760.             {
  761.                 for ( var j = 0; j < currNode.childNodes.length; j++ )
  762.                 {
  763.                     ConvertIndexLinksToAbsolute( currNode.childNodes[j] );
  764.                 }
  765.             }
  766.             else if ( currNode.nodeName == "Links" )
  767.             {
  768.                 for ( var j = 0; j < currNode.childNodes.length; j++ )
  769.                 {
  770.                     if ( currNode.childNodes[j].nodeType == 1 )
  771.                     {
  772.                         var link    = FMCGetAttribute( currNode.childNodes[j], "Link" );
  773.                         
  774.                         link = mPath + ((link.charAt( 0 ) == "/") ? link.substring( 1, link.length ) : link);
  775.                         currNode.childNodes[j].setAttribute( "Link", link );
  776.                     }
  777.                 }
  778.             }
  779.         }
  780.     }
  781.     
  782.     function LoadConcepts()
  783.     {
  784.         if ( mConceptMap )
  785.         {
  786.             return;
  787.         }
  788.         
  789.         mConceptMap = new CMCDictionary();
  790.         
  791.         var xmlDoc    = CMCXmlParser.GetXmlDoc( mPath + "Data/Concepts.xml", false, null, null );
  792.         var xmlHead    = xmlDoc.documentElement;
  793.         
  794.         for ( var i = 0; i < xmlHead.childNodes.length; i++ )
  795.         {
  796.             var entry   = xmlHead.childNodes[i];
  797.             
  798.             if ( entry.nodeType != 1 ) { continue; }
  799.             
  800.             var term    = entry.getAttribute( "Term" ).toLowerCase();
  801.             var links   = new Array();
  802.             
  803.             for ( var j = 0; j < entry.childNodes.length; j++ )
  804.             {
  805.                 var link    = entry.childNodes[j];
  806.                 
  807.                 if ( link.nodeType != 1 ) { continue; }
  808.                 
  809.                 var title   = link.getAttribute( "Title" );
  810.                 var url     = link.getAttribute( "Link" );
  811.                 
  812.                 url = mPath + ((url.charAt( 0 ) == "/") ? url.substring( 1, url.length ) : url);
  813.                 
  814.                 links[links.length] = title + "|" + url;
  815.             }
  816.             
  817.             mConceptMap.Add( term, links );
  818.         }
  819.     }
  820.     
  821.     function MergeConceptLinks( links1, links2 )
  822.     {
  823.         if ( !links2 )
  824.         {
  825.             return;
  826.         }
  827.         
  828.         for ( var i = 0; i < links2.length; i++ )
  829.         {
  830.             links1[links1.length] = links2[i];
  831.         }
  832.     }
  833.     
  834.     function MergeGlossaries( xmlDoc1, subsystem )
  835.     {
  836.         var xmlDoc2    = subsystem.GetGlossary();
  837.         var divs1   = xmlDoc1.getElementsByTagName( "div" );
  838.         var divs2   = xmlDoc2.getElementsByTagName( "div" );
  839.         var body1   = null;
  840.         var body2   = null;
  841.         var body    = xmlDoc1.createElement( "div" );
  842.         
  843.         body.setAttribute( "id", "GlossaryBody" );
  844.         
  845.         for ( var i = 0; i < divs1.length; i++ )
  846.         {
  847.             if ( divs1[i].getAttribute( "id" ) == "GlossaryBody" )
  848.             {
  849.                 body1 = divs1[i];
  850.                 break;
  851.             }
  852.         }
  853.         
  854.         for ( var i = 0; i < divs2.length; i++ )
  855.         {
  856.             if ( divs2[i].getAttribute( "id" ) == "GlossaryBody" )
  857.             {
  858.                 body2 = divs2[i];
  859.                 break;
  860.             }
  861.         }
  862.         
  863.         //
  864.         
  865.         var glossUrl    = subsystem.GlossaryUrl;
  866.         var pos            = glossUrl.lastIndexOf( "/" );
  867.         var subPath        = glossUrl.substring( 0, pos + 1 );
  868.         
  869.         //
  870.         
  871.         if ( body1.getElementsByTagName( "div" ).length == 0 )
  872.         {
  873.             if ( typeof( xmlDoc1.importNode ) == "function" )
  874.             {
  875.                 body = xmlDoc1.importNode( body2, true );
  876.             }
  877.             else
  878.             {
  879.                 body = body2.cloneNode( true );
  880.             }
  881.             
  882.             for ( var i = 0; i < body.childNodes.length; i++ )
  883.             {
  884.                 var currNode    = body.childNodes[i];
  885.                 
  886.                 if ( currNode.nodeType != 1 || currNode.nodeName != "div" )
  887.                 {
  888.                     continue;
  889.                 }
  890.                 
  891.                 ConvertGlossaryPageEntryToAbsolute( currNode, subPath );
  892.             }
  893.         }
  894.         else if ( body2.getElementsByTagName( "div" ).length == 0 )
  895.         {
  896.             body = body1.cloneNode( true );
  897.         }
  898.         else
  899.         {
  900.             for ( var i = 0, j = 0; i < body1.childNodes.length && j < body2.childNodes.length; )
  901.             {
  902.                 var currGlossaryPageEntry1  = body1.childNodes[i];
  903.                 var currGlossaryPageEntry2  = body2.childNodes[j];
  904.                 
  905.                 if ( currGlossaryPageEntry1.nodeType != 1 )
  906.                 {
  907.                     i++;
  908.                     continue;
  909.                 }
  910.                 else if ( currGlossaryPageEntry2.nodeType != 1 )
  911.                 {
  912.                     j++;
  913.                     continue;
  914.                 }
  915.                 
  916.                 var term1   = currGlossaryPageEntry1.getElementsByTagName( "div" )[0].getElementsByTagName( "a" )[0].firstChild.nodeValue;
  917.                 var term2   = currGlossaryPageEntry2.getElementsByTagName( "div" )[0].getElementsByTagName( "a" )[0].firstChild.nodeValue;
  918.                 
  919.                 if ( term1.toLowerCase() == term2.toLowerCase() )
  920.                 {
  921.                     body.appendChild( currGlossaryPageEntry1.cloneNode( true ) );
  922.                     i++;
  923.                     j++;
  924.                 }
  925.                 else if ( term1.toLowerCase() > term2.toLowerCase() )
  926.                 {
  927.                     var newGlossaryPageEntry    = null;
  928.                     
  929.                     if ( typeof( xmlDoc1.importNode ) == "function" )
  930.                     {
  931.                         newGlossaryPageEntry = xmlDoc1.importNode( currGlossaryPageEntry2, true );
  932.                     }
  933.                     else
  934.                     {
  935.                         newGlossaryPageEntry = currGlossaryPageEntry2.cloneNode( true );
  936.                     }
  937.                     
  938.                     ConvertGlossaryPageEntryToAbsolute( newGlossaryPageEntry, subPath );
  939.                     body.appendChild( newGlossaryPageEntry )
  940.                     
  941.                     j++;
  942.                 }
  943.                 else
  944.                 {
  945.                     body.appendChild( currGlossaryPageEntry1.cloneNode( true ) );
  946.                     i++;
  947.                 }
  948.             }
  949.             
  950.             // Append remaining nodes. There should never be a case where BOTH entries1 AND entries2 have remaining nodes.
  951.             
  952.             for ( ; i < body1.childNodes.length; i++ )
  953.             {
  954.                 body.appendChild( body1.childNodes[i].cloneNode( true ) );
  955.             }
  956.             
  957.             for ( ; j < body2.childNodes.length; j++ )
  958.             {
  959.                 var currNode    = body2.childNodes[j];
  960.                 
  961.                 if ( currNode.nodeType != 1 )
  962.                 {
  963.                     continue;
  964.                 }
  965.                 
  966.                 var newNode        = null;
  967.                 
  968.                 if ( typeof( xmlDoc1.importNode ) == "function" )
  969.                 {
  970.                     newNode = xmlDoc1.importNode( body2.childNodes[j], true );
  971.                 }
  972.                 else
  973.                 {
  974.                     newNode = body2.childNodes[j].cloneNode( true );
  975.                 }
  976.                 
  977.                 ConvertGlossaryPageEntryToAbsolute( newNode, subPath );
  978.                 body.appendChild( newNode );
  979.             }
  980.         }
  981.         
  982.         body1.parentNode.replaceChild( body, body1 );
  983.     }
  984. }
  985.  
  986. //
  987. //    End class CMCHelpSystem
  988. //
  989.  
  990. /* -CatapultCompiler- -End- -Copy to CSH Javascript- */
  991.  
  992. /* -CatapultCompiler- -Begin- -Copy to CSH Javascript- */
  993.  
  994. //
  995. //    Enumeration EMCTocType
  996. //
  997.  
  998. var EMCTocType    = new function()
  999. {
  1000. }
  1001.  
  1002. EMCTocType.Toc                = 0;
  1003. EMCTocType.BrowseSequence    = 1;
  1004.  
  1005. //
  1006. //    End enumeration EMCTocType
  1007. //
  1008.  
  1009. /* -CatapultCompiler- -End- -Copy to CSH Javascript- */
  1010.  
  1011. /* -CatapultCompiler- -Begin- -Copy to CSH Javascript- */
  1012.  
  1013. //
  1014. //    Class CMCTocFile
  1015. //
  1016.  
  1017. function CMCTocFile( helpSystem, tocType )
  1018. {
  1019.     // Private member variables
  1020.  
  1021.     var mSelf                    = this;
  1022.     var mHelpSystem                = helpSystem;
  1023.     var mTocType                = tocType;
  1024.     var mInitialized            = false;
  1025.     var mXmlDoc                    = null;
  1026.     var mInitOnCompleteFuncs    = new Array();
  1027.     var mTocPath                = null;
  1028.     var mTocHref                = null;
  1029.     var mOwnerHelpSystems        = new Array();
  1030.  
  1031.     // Public properties
  1032.  
  1033.     // Constructor
  1034.  
  1035.     (function()
  1036.     {
  1037.     })();
  1038.  
  1039.     // Public member functions
  1040.     
  1041.     this.Init = function( OnCompleteFunc )
  1042.     {
  1043.         if ( mInitialized )
  1044.         {
  1045.             if ( OnCompleteFunc != null )
  1046.             {
  1047.                 OnCompleteFunc();
  1048.             }
  1049.             
  1050.             return;
  1051.         }
  1052.         
  1053.         //
  1054.  
  1055.         if ( OnCompleteFunc != null )
  1056.         {
  1057.             mInitOnCompleteFuncs.push( OnCompleteFunc );
  1058.         }
  1059.         
  1060.         //
  1061.         
  1062.         var fileName = null;
  1063.         
  1064.         if ( tocType == EMCTocType.Toc )
  1065.         {
  1066.             fileName = "Toc.xml";
  1067.         }
  1068.         else if ( tocType == EMCTocType.BrowseSequence )
  1069.         {
  1070.             fileName = "BrowseSequences.xml";
  1071.         }
  1072.         
  1073.         this.LoadToc( mHelpSystem.GetPath() + "Data/" + fileName, OnLoadTocComplete );
  1074.         
  1075.         function OnLoadTocComplete( xmlDoc )
  1076.         {
  1077.             mInitialized = true;
  1078.             
  1079.             mXmlDoc = xmlDoc;
  1080.  
  1081.             InitOnComplete();
  1082.         }
  1083.     };
  1084.     
  1085.     this.LoadToc = function( xmlFile, OnCompleteFunc )
  1086.     {
  1087.         var masterHS = FMCGetHelpSystem();
  1088.         var xmlDoc = null;
  1089.         
  1090.         if ( mTocType == EMCTocType.Toc && masterHS.IsWebHelpPlus )
  1091.         {
  1092.             xmlDoc = CMCXmlParser.CallWebService( mHelpSystem.GetPath() + "Service/Service.asmx/GetToc", true, OnTocXmlLoaded, null );
  1093.         }
  1094.         else if ( mTocType == EMCTocType.BrowseSequence && masterHS.IsWebHelpPlus )
  1095.         {
  1096.             xmlDoc = CMCXmlParser.CallWebService( mHelpSystem.GetPath() + "Service/Service.asmx/GetBrowseSequences", true, OnTocXmlLoaded, null );
  1097.         }
  1098.         else
  1099.         {
  1100.             var xmlPath    = (xmlFile.indexOf( "/" ) == -1) ? mHelpSystem.GetPath() + "Data/" + xmlFile : xmlFile;
  1101.             
  1102.             xmlDoc = CMCXmlParser.GetXmlDoc( xmlPath, true, OnTocXmlLoaded, null );
  1103.         }
  1104.         
  1105.         function OnTocXmlLoaded( xmlDoc, args )
  1106.         {
  1107.             if ( !xmlDoc || !xmlDoc.documentElement )
  1108.             {
  1109.                 if ( OnCompleteFunc != null )
  1110.                 {
  1111.                     OnCompleteFunc( xmlDoc );
  1112.                 }
  1113.                 
  1114.                 return;
  1115.             }
  1116.             
  1117.             //
  1118.             
  1119.             if ( OnCompleteFunc != null )
  1120.             {
  1121.                 OnCompleteFunc( xmlDoc );
  1122.             }
  1123.         }
  1124.     };
  1125.     
  1126.     this.LoadChunk = function( parentNode, xmlFile, OnCompleteFunc )
  1127.     {
  1128.         var xmlPath    = (xmlFile.indexOf( "/" ) == -1) ? mHelpSystem.GetPath() + "Data/" + xmlFile : xmlFile;
  1129.         var xmlDoc = CMCXmlParser.GetXmlDoc( xmlPath, true, OnTocXmlLoaded, null );
  1130.         
  1131.         function OnTocXmlLoaded( xmlDoc, args )
  1132.         {
  1133.             if ( !xmlDoc || !xmlDoc.documentElement )
  1134.             {
  1135.                 if ( OnCompleteFunc != null )
  1136.                 {
  1137.                     OnCompleteFunc( parentNode );
  1138.                 }
  1139.                 
  1140.                 return;
  1141.             }
  1142.             
  1143.             parentNode.removeAttribute( "Chunk" );
  1144.             
  1145.             var rootNode = xmlDoc.documentElement;
  1146.             
  1147.             for ( var i = 0, length = rootNode.childNodes.length; i < length; i++ )
  1148.             {
  1149.                 var childNode = rootNode.childNodes[i];
  1150.                 
  1151.                 if ( childNode.nodeType != 1 ) { continue; }
  1152.                 
  1153.                 var importedNode = null;
  1154.                 
  1155.                 if ( typeof( xmlDoc.importNode ) == "function" )
  1156.                 {
  1157.                     importedNode = xmlDoc.importNode( childNode, true );
  1158.                 }
  1159.                 else
  1160.                 {
  1161.                     importedNode = childNode.cloneNode( true );
  1162.                 }
  1163.                 
  1164.                 parentNode.appendChild( importedNode );
  1165.             }
  1166.             
  1167.             //
  1168.             
  1169.             if ( OnCompleteFunc != null )
  1170.             {
  1171.                 OnCompleteFunc( parentNode );
  1172.             }
  1173.         }
  1174.     }
  1175.     
  1176.     this.LoadMerge = function( parentNode, OnCompleteFunc )
  1177.     {
  1178.         var mergeHint = FMCGetAttributeInt( parentNode, "MergeHint", -1 );
  1179.         
  1180.         if ( mergeHint == -1 )
  1181.         {
  1182.             OnCompleteFunc( parentNode, false, null, null );
  1183.         }
  1184.         
  1185.         parentNode.removeAttribute( "MergeHint" );
  1186.         
  1187.         var ownerHelpSystem = GetOwnerHelpSystem( parentNode );
  1188.         var subsystem = ownerHelpSystem.GetSubsystem( mergeHint );
  1189.         var replace = FMCGetAttributeBool( parentNode, "ReplaceMergeNode", false );
  1190.             
  1191.         if ( !replace )
  1192.         {
  1193.             parentNode.setAttribute( "ownerHelpSystemIndex", mOwnerHelpSystems.length );
  1194.         }
  1195.         
  1196.         mOwnerHelpSystems[mOwnerHelpSystems.length] = subsystem;
  1197.         
  1198.         var xmlPath = subsystem.GetPath() + "Data/" + (mTocType == EMCTocType.Toc ? "Toc.xml" : "BrowseSequences.xml");
  1199.         var xmlDoc = CMCXmlParser.GetXmlDoc( xmlPath, true, OnTocXmlLoaded, null );
  1200.         
  1201.         function OnTocXmlLoaded( xmlDoc, args )
  1202.         {
  1203.             if ( !xmlDoc || !xmlDoc.documentElement )
  1204.             {
  1205.                 if ( OnCompleteFunc != null )
  1206.                 {
  1207.                     OnCompleteFunc( parentNode, false, null, null );
  1208.                 }
  1209.                 
  1210.                 return;
  1211.             }
  1212.  
  1213.             var rootNode = xmlDoc.documentElement;
  1214.             var currNode = null;
  1215.             var isFirst = true;
  1216.             var firstNode = null;
  1217.             var lastNode = null;
  1218.             
  1219.             for ( var i = 0, length = rootNode.childNodes.length; i < length; i++ )
  1220.             {
  1221.                 var childNode = rootNode.childNodes[i];
  1222.                 
  1223.                 if ( childNode.nodeType != 1 ) { continue; }
  1224.                 
  1225.                 var importedNode = null;
  1226.                 
  1227.                 if ( typeof( xmlDoc.importNode ) == "function" )
  1228.                 {
  1229.                     importedNode = xmlDoc.importNode( childNode, true );
  1230.                 }
  1231.                 else
  1232.                 {
  1233.                     importedNode = childNode.cloneNode( true );
  1234.                 }
  1235.                 
  1236.                 if ( replace )
  1237.                 {
  1238.                     importedNode.setAttribute( "ownerHelpSystemIndex", mOwnerHelpSystems.length - 1 );
  1239.                     
  1240.                     if ( isFirst )
  1241.                     {
  1242.                         isFirst = false;
  1243.                         
  1244.                         parentNode.parentNode.replaceChild( importedNode, parentNode );
  1245.                         
  1246.                         firstNode = importedNode;
  1247.                         
  1248.                         currNode = importedNode;
  1249.                     }
  1250.                     else
  1251.                     {
  1252.                         currNode.parentNode.insertBefore( importedNode, currNode.nextSibling );
  1253.                         
  1254.                         lastNode = importedNode;
  1255.                     }
  1256.                 }
  1257.                 else
  1258.                 {
  1259.                     parentNode.appendChild( importedNode );
  1260.                 }
  1261.             }
  1262.             
  1263.             //
  1264.             
  1265.             if ( OnCompleteFunc != null )
  1266.             {
  1267.                 OnCompleteFunc( parentNode, replace, firstNode, lastNode );
  1268.             }
  1269.         }
  1270.     }
  1271.     
  1272.     this.AdvanceTopic = function( moveType, tocPath, href )
  1273.     {
  1274.         this.GetTocNode( tocPath, href, OnComplete );
  1275.  
  1276.         function OnComplete( tocNode )
  1277.         {
  1278.             if ( tocNode == null )
  1279.             {
  1280.                 return;
  1281.             }
  1282.             
  1283.             var moveNode = null;
  1284.             
  1285.             GetMoveTocTopicNode( moveType, tocNode, OnGetMoveTocNodeComplete );
  1286.             
  1287.             function OnGetMoveTocNodeComplete( moveNode )
  1288.             {
  1289.                 if ( moveNode != null )
  1290.                 {
  1291.                     var href = FMCGetAttribute( moveNode, "Link" );
  1292.                     
  1293.                     if ( FMCIsHtmlHelp() )
  1294.                     {
  1295.                         href = href.substring( "/Content/".length );
  1296.                     }
  1297.                     else
  1298.                     {
  1299.                         href = href.substring( "/".length );
  1300.                     }
  1301.  
  1302.                     var hrefUrl = new CMCUrl( href );
  1303.  
  1304.                     // CHMs don't support query strings in links
  1305.                     if ( !FMCIsHtmlHelp() )
  1306.                     {
  1307.                         var prefix = null;
  1308.                         
  1309.                         if ( mTocType == EMCTocType.Toc )
  1310.                         {
  1311.                             prefix = "TocPath";
  1312.                         }
  1313.                         else if ( mTocType == EMCTocType.BrowseSequence )
  1314.                         {
  1315.                             prefix = "BrowseSequencePath";
  1316.                         }
  1317.  
  1318.                         var tocPath = GetTocPath(moveNode);
  1319.                         var newHrefUrl = hrefUrl.ToQuery( prefix + "=" + encodeURIComponent( tocPath ) );
  1320.                         
  1321.                         href = newHrefUrl.FullPath;
  1322.                     }
  1323.                     
  1324.                     var subsystem = GetOwnerHelpSystem( moveNode );
  1325.                     
  1326.                     href = subsystem.GetPath() + href;
  1327.                     
  1328.                     MCGlobals.BodyFrame.document.location.href = href;
  1329.                 }
  1330.             }
  1331.         }
  1332.     };
  1333.     
  1334.     this.GetRootNode = function( onCompleteFunc )
  1335.     {
  1336.         this.Init( OnInit );
  1337.         
  1338.         function OnInit()
  1339.         {
  1340.             onCompleteFunc( mXmlDoc.documentElement );
  1341.         }
  1342.     };
  1343.     
  1344.     this.GetTocNode = function( tocPath, href, onCompleteFunc )
  1345.     {
  1346.         this.Init( OnInit );
  1347.  
  1348.         function OnInit()
  1349.         {
  1350.             mTocPath = tocPath;
  1351.             mTocHref = href;
  1352.  
  1353.             //
  1354.  
  1355.             var steps = (tocPath == "") ? new Array( 0 ) : tocPath.split( "|" );
  1356.             var linkNodeIndex = -1;
  1357.             
  1358.             if ( steps.length > 0 )
  1359.             {
  1360.                 var lastStep = steps[steps.length - 1];
  1361.                 
  1362.                 if ( lastStep.StartsWith( "$$$$$" ) )
  1363.                 {
  1364.                     linkNodeIndex = parseInt( lastStep.substring( "$$$$$".length ) );
  1365.                     steps.splice( steps.length - 1, 1 );
  1366.                 }
  1367.             }
  1368.             
  1369.             var tocNode = mXmlDoc.documentElement;
  1370.  
  1371.             for ( var i = 0, length = steps.length; i < length; i++ )
  1372.             {
  1373.                 if ( CheckChunk( tocNode ) )
  1374.                 {
  1375.                     return;
  1376.                 }
  1377.                 
  1378.                 if ( CheckMerge( tocNode ) )
  1379.                 {
  1380.                     return;
  1381.                 }
  1382.                 
  1383.                 //
  1384.                 
  1385.                 tocNode = FindBook( tocNode, steps[i] );
  1386.             }
  1387.  
  1388.             if ( tocNode == null )
  1389.             {
  1390.                 onCompleteFunc( null );
  1391.                 
  1392.                 return;
  1393.             }
  1394.             
  1395.             if ( CheckChunk( tocNode ) )
  1396.             {
  1397.                 return;
  1398.             }
  1399.             
  1400.             if ( CheckMerge( tocNode ) )
  1401.             {
  1402.                 return;
  1403.             }
  1404.             
  1405.             if ( linkNodeIndex >= 0 )
  1406.             {
  1407.                 if ( linkNodeIndex == 0 )
  1408.                 {
  1409.                     foundNode = tocNode;
  1410.                 }
  1411.                 else
  1412.                 {
  1413.                     foundNode = FMCGetChildNodeByTagName( tocNode, "TocEntry", linkNodeIndex - 1 );
  1414.                 }
  1415.             }
  1416.             else
  1417.             {
  1418.                 var ownerHelpSystem = GetOwnerHelpSystem( tocNode );
  1419.                 var relHref = href.ToRelative( new CMCUrl( ownerHelpSystem.GetPath() ) );
  1420.                 var foundNode = FindLink( tocNode, relHref.FullPath.toLowerCase(), true );
  1421.  
  1422.                 if ( !foundNode )
  1423.                 {
  1424.                     foundNode = FindLink( tocNode, relHref.PlainPath.toLowerCase(), false );
  1425.                 }
  1426.             }
  1427.             
  1428.             //
  1429.  
  1430.             mTocPath = null;
  1431.             mTocHref = null;
  1432.             
  1433.             //
  1434.             
  1435.             onCompleteFunc( foundNode );
  1436.         }
  1437.         
  1438.         function CheckChunk( tocNode )
  1439.         {
  1440.             var chunk = FMCGetAttribute( tocNode, "Chunk" );
  1441.  
  1442.             if ( chunk != null )
  1443.             {
  1444.                 mSelf.LoadChunk( tocNode, chunk,
  1445.                     function( tocNode )
  1446.                     {
  1447.                         mSelf.GetTocNode( mTocPath, mTocHref, onCompleteFunc )
  1448.                     }
  1449.                 );
  1450.  
  1451.                 return true;
  1452.             }
  1453.             
  1454.             return false;
  1455.         }
  1456.         
  1457.         function CheckMerge( tocNode )
  1458.         {
  1459.             var mergeHint = FMCGetAttributeInt( tocNode, "MergeHint", -1 );
  1460.  
  1461.             if ( mergeHint >= 0 )
  1462.             {
  1463.                 mSelf.LoadMerge( tocNode,
  1464.                     function( tocNode )
  1465.                     {
  1466.                         mSelf.GetTocNode( mTocPath, mTocHref, onCompleteFunc )
  1467.                     }
  1468.                 );
  1469.                 
  1470.                 return true;
  1471.             }
  1472.             
  1473.             return false;
  1474.         }
  1475.     };
  1476.     
  1477.     this.GetEntrySequenceIndex = function( tocPath, href, onCompleteFunc )
  1478.     {
  1479.         this.GetTocNode( tocPath, href, OnCompleteGetTocNode );
  1480.         
  1481.         function OnCompleteGetTocNode( tocNode )
  1482.         {
  1483.             var sequenceIndex = -1;
  1484.             
  1485.             if ( tocNode != null )
  1486.             {
  1487.                 sequenceIndex = ComputeEntrySequenceIndex( tocNode );
  1488.             }
  1489.             
  1490.             onCompleteFunc( sequenceIndex );
  1491.         }
  1492.     };
  1493.     
  1494.     this.GetIndexTotalForEntry = function( tocPath, href, onCompleteFunc )
  1495.     {
  1496.         this.GetTocNode( tocPath, href, OnCompleteGetTocNode );
  1497.         
  1498.         function OnCompleteGetTocNode( tocNode )
  1499.         {
  1500.             var total = -1;
  1501.             
  1502.             if ( tocNode != null )
  1503.             {
  1504.                 var currNode = tocNode;
  1505.                 
  1506.                 while ( currNode.parentNode != mXmlDoc.documentElement )
  1507.                 {
  1508.                     currNode = currNode.parentNode;
  1509.                 }
  1510.                 
  1511.                 total = FMCGetAttributeInt( currNode, "DescendantCount", -1 );
  1512.             }
  1513.             
  1514.             onCompleteFunc( total );
  1515.         }
  1516.     };
  1517.     
  1518.     // Private member functions
  1519.     
  1520.     function InitOnComplete()
  1521.     {
  1522.         for ( var i = 0, length = mInitOnCompleteFuncs.length; i < length; i++ )
  1523.         {
  1524.             mInitOnCompleteFuncs[i]();
  1525.         }
  1526.     }
  1527.     
  1528.     function FindBook( tocNode, step )
  1529.     {
  1530.         var foundNode = null;
  1531.  
  1532.         for ( var i = 0; i < tocNode.childNodes.length; i++ )
  1533.         {
  1534.             if ( tocNode.childNodes[i].nodeName == "TocEntry" && FMCGetAttribute( tocNode.childNodes[i], "Title" ) == step )
  1535.             {
  1536.                 foundNode = tocNode.childNodes[i];
  1537.                 
  1538.                 break;
  1539.             }
  1540.         }
  1541.         
  1542.         return foundNode;
  1543.     }
  1544.  
  1545.     function FindLink( node, bodyHref, exactMatch )
  1546.     {
  1547.         var foundNode = null;
  1548.         var bookHref = FMCGetAttribute( node, "Link" );
  1549.  
  1550.         if ( bookHref != null )
  1551.         {
  1552.             if ( FMCIsHtmlHelp() )
  1553.             {
  1554.                 bookHref = bookHref.substring( "/Content/".length );
  1555.             }
  1556.             else
  1557.             {
  1558.                 bookHref = bookHref.substring( "/".length );
  1559.             }
  1560.             
  1561.             bookHref = bookHref.replace( /%20/g, " " );
  1562.             bookHref = bookHref.toLowerCase();
  1563.         }
  1564.         
  1565.         if ( bookHref == bodyHref )
  1566.         {
  1567.             foundNode = node;
  1568.         }
  1569.         else
  1570.         {
  1571.             for ( var k = 0; k < node.childNodes.length; k++ )
  1572.             {
  1573.                 var currNode = node.childNodes[k];
  1574.                 
  1575.                 if ( currNode.nodeType != 1 ) { continue; }
  1576.                 
  1577.                 var currTopicHref = FMCGetAttribute( currNode, "Link" );
  1578.                 
  1579.                 if ( currTopicHref == null )
  1580.                 {
  1581.                     continue;
  1582.                 }
  1583.                 
  1584.                 if ( FMCIsHtmlHelp() )
  1585.                 {
  1586.                     currTopicHref = currTopicHref.substring( "/Content/".length );
  1587.                 }
  1588.                 else
  1589.                 {
  1590.                     currTopicHref = currTopicHref.substring( "/".length );
  1591.                 }
  1592.  
  1593.                 currTopicHref = currTopicHref.replace( /%20/g, " " );
  1594.                 currTopicHref = currTopicHref.toLowerCase();
  1595.                 
  1596.                 if ( !exactMatch )
  1597.                 {
  1598.                     var hashPos = currTopicHref.indexOf( "#" );
  1599.  
  1600.                     if ( hashPos != -1 )
  1601.                     {
  1602.                         currTopicHref = currTopicHref.substring( 0, hashPos );
  1603.                     }
  1604.                     
  1605.                     var searchPos = currTopicHref.indexOf( "?" );
  1606.                     
  1607.                     if ( searchPos != -1 )
  1608.                     {
  1609.                         currTopicHref = currTopicHref.substring( 0, searchPos );
  1610.                     }
  1611.                 }
  1612.                 
  1613.                 if ( currTopicHref == bodyHref )
  1614.                 {
  1615.                     foundNode = currNode;
  1616.                     
  1617.                     break;
  1618.                 }
  1619.             }
  1620.         }
  1621.         
  1622.         return foundNode;
  1623.     }
  1624.     
  1625.     function GetMoveTocTopicNode( moveType, tocNode, onCompleteFunc )
  1626.     {
  1627.         if ( moveType == "previous" )
  1628.         {
  1629.             GetPreviousNode( tocNode );
  1630.         }
  1631.         else if ( moveType == "next" )
  1632.         {
  1633.             GetNextNode( tocNode );
  1634.         }
  1635.         
  1636.         function OnCompleteGetNode( moveNode )
  1637.         {
  1638.             var moveTopicNode = null;
  1639.             
  1640.             if ( moveNode != null )
  1641.             {
  1642.                 var link = FMCGetAttribute( moveNode, "Link" );
  1643.                 
  1644.                 if ( link == null )
  1645.                 {
  1646.                     GetMoveTocTopicNode( moveType, moveNode, onCompleteFunc );
  1647.  
  1648.                     return;
  1649.                 }
  1650.                 
  1651.                 var linkUrl = new CMCUrl( link );
  1652.                 var ext = linkUrl.Extension.toLowerCase();
  1653.                 
  1654.                 if ( ext != "htm" && ext != "html" )
  1655.                 {
  1656.                     GetMoveTocTopicNode( moveType, moveNode, onCompleteFunc );
  1657.  
  1658.                     return;
  1659.                 }
  1660.                 
  1661.                 moveTopicNode = moveNode;
  1662.             }
  1663.             
  1664.             onCompleteFunc( moveTopicNode );
  1665.         }
  1666.  
  1667.         function GetPreviousNode( tocNode )
  1668.         {
  1669.             function OnLoadChunk( tNode )
  1670.             {
  1671.                 var childTocNode = GetDeepestChild( tNode, "TocEntry" );
  1672.                 
  1673.                 if ( childTocNode == null )
  1674.                 {
  1675.                     previousNode = tNode;
  1676.                 }
  1677.                 else
  1678.                 {
  1679.                     previousNode = childTocNode;
  1680.                     
  1681.                     if ( CheckChunk( childTocNode, OnLoadChunk ) )
  1682.                     {
  1683.                         return;
  1684.                     }
  1685.                     
  1686.                     if ( CheckMerge( childTocNode, OnLoadMerge ) )
  1687.                     {
  1688.                         return;
  1689.                     }
  1690.                 }
  1691.                 
  1692.                 OnCompleteGetNode( previousNode );
  1693.             }
  1694.             
  1695.             function OnLoadMerge( tNode, replaced, firstNode, lastNode )
  1696.             {
  1697.                 if ( replaced )
  1698.                 {
  1699.                     OnLoadChunk( lastNode );
  1700.                 }
  1701.                 else
  1702.                 {
  1703.                     OnLoadChunk( tNode );
  1704.                 }
  1705.             }
  1706.             
  1707.             var previousNode = null;
  1708.             
  1709.             for ( var currNode = tocNode.previousSibling; currNode != null; currNode = currNode.previousSibling )
  1710.             {
  1711.                 if ( currNode.nodeName == "TocEntry" )
  1712.                 {
  1713.                     previousNode = currNode;
  1714.                     break;
  1715.                 }
  1716.             }
  1717.             
  1718.             if ( previousNode != null )
  1719.             {
  1720.                 if ( CheckChunk( previousNode, OnLoadChunk ) )
  1721.                 {
  1722.                     return;
  1723.                 }
  1724.                 
  1725.                 if ( CheckMerge( previousNode, OnLoadMerge ) )
  1726.                 {
  1727.                     return;
  1728.                 }
  1729.  
  1730.                 OnLoadChunk( previousNode );
  1731.                 
  1732.                 return;
  1733.             }
  1734.             else
  1735.             {
  1736.                 if ( tocNode.parentNode.nodeType == 1 )
  1737.                 {
  1738.                     previousNode = tocNode.parentNode;
  1739.                 }
  1740.             }
  1741.             
  1742.             OnCompleteGetNode( previousNode );
  1743.         }
  1744.         
  1745.         function GetNextNode( tocNode )
  1746.         {
  1747.             function OnLoadChunk( tNode )
  1748.             {
  1749.                 var nextNode = FMCGetChildNodeByTagName( tNode, "TocEntry", 0 );
  1750.                 
  1751.                 for ( var currNode = tNode; currNode != null && nextNode == null; currNode = currNode.parentNode )
  1752.                 {
  1753.                     nextNode = FMCGetSiblingNodeByTagName( currNode, "TocEntry" );
  1754.                 }
  1755.                 
  1756.                 OnCompleteGetNode( nextNode );
  1757.             }
  1758.             
  1759.             function OnLoadMerge( tNode, replaced, firstNode, lastNode )
  1760.             {
  1761.                 if ( replaced )
  1762.                 {
  1763.                     OnCompleteGetNode( firstNode );
  1764.                     
  1765.                     return;
  1766.                 }
  1767.                 
  1768.                 OnLoadChunk( tNode );
  1769.             }
  1770.             
  1771.             var nextNode = null;
  1772.             
  1773.             if ( CheckChunk( tocNode, OnLoadChunk ) )
  1774.             {
  1775.                 return;
  1776.             }
  1777.             
  1778.             if ( CheckMerge( tocNode, OnLoadMerge ) )
  1779.             {
  1780.                 return;
  1781.             }
  1782.             
  1783.             OnLoadChunk( tocNode );
  1784.         }
  1785.         
  1786.         function CheckChunk( tocNode, OnCompleteFunc )
  1787.         {
  1788.             var chunk = FMCGetAttribute( tocNode, "Chunk" );
  1789.  
  1790.             if ( chunk != null )
  1791.             {
  1792.                 mSelf.LoadChunk( tocNode, chunk, OnCompleteFunc );
  1793.  
  1794.                 return true;
  1795.             }
  1796.             
  1797.             return false;
  1798.         }
  1799.         
  1800.         function CheckMerge( tocNode, OnCompleteFunc )
  1801.         {
  1802.             var mergeHint = FMCGetAttributeInt( tocNode, "MergeHint", -1 );
  1803.  
  1804.             if ( mergeHint >= 0 )
  1805.             {
  1806.                 mSelf.LoadMerge( tocNode, OnCompleteFunc );
  1807.                 
  1808.                 return true;
  1809.             }
  1810.             
  1811.             return false;
  1812.         }
  1813.     }
  1814.     
  1815.     function GetDeepestChild( tocNode, nodeName )
  1816.     {
  1817.         var node = FMCGetLastChildNodeByTagName( tocNode, nodeName );
  1818.         
  1819.         if ( node != null )
  1820.         {
  1821.             var nodeChild = GetDeepestChild( node, nodeName );
  1822.             
  1823.             if ( nodeChild != null )
  1824.             {
  1825.                 return nodeChild;
  1826.             }
  1827.             
  1828.             return node;
  1829.         }
  1830.         
  1831.         return null;
  1832.     }
  1833.     
  1834.     function GetOwnerHelpSystem( tocNode )
  1835.     {
  1836.         var ownerHelpSystem = null;
  1837.         var currNode = tocNode;
  1838.  
  1839.         while ( true )
  1840.         {
  1841.             if ( currNode == currNode.ownerDocument.documentElement )
  1842.             {
  1843.                 ownerHelpSystem = mHelpSystem;
  1844.  
  1845.                 break;
  1846.             }
  1847.             
  1848.             var ownerHelpSystemIndex = FMCGetAttributeInt( currNode, "ownerHelpSystemIndex", -1 );
  1849.  
  1850.             if ( ownerHelpSystemIndex >= 0 )
  1851.             {
  1852.                 ownerHelpSystem = mOwnerHelpSystems[ownerHelpSystemIndex];
  1853.                 
  1854.                 break;
  1855.             }
  1856.             
  1857.             currNode = currNode.parentNode;
  1858.         }
  1859.  
  1860.         return ownerHelpSystem;
  1861.     }
  1862.     
  1863.     function GetTocPath( tocNode )
  1864.     {
  1865.         var tocPath = "";
  1866.         var linkNodeIndex = -1;
  1867.         var childNode = FMCGetChildNodeByTagName( tocNode, "TocEntry", 0 );
  1868.  
  1869.         if ( childNode != null )
  1870.         {
  1871.             tocPath = FMCGetAttribute( tocNode, "Title" );
  1872.             
  1873.             linkNodeIndex = 0;
  1874.         }
  1875.         else
  1876.         {
  1877.             linkNodeIndex = FMCGetChildIndex( tocNode ) + 1;
  1878.         }
  1879.         
  1880.         if ( tocPath.length > 0 )
  1881.         {
  1882.             tocPath += "|";
  1883.         }
  1884.         
  1885.         tocPath += ("$$$$$" + linkNodeIndex);
  1886.         
  1887.         for ( var currNode = tocNode.parentNode; currNode != null && currNode.parentNode.nodeType == 1; currNode = currNode.parentNode )
  1888.         {
  1889.             if ( tocPath == null )
  1890.             {
  1891.                 tocPath = "";
  1892.             }
  1893.             
  1894.             if ( tocPath.length > 0 )
  1895.             {
  1896.                 tocPath = "|" + tocPath;
  1897.             }
  1898.             
  1899.             tocPath = FMCGetAttribute( currNode, "Title" ) + tocPath;
  1900.         }
  1901.         
  1902.         return tocPath;
  1903.     }
  1904.     
  1905.     function ComputeEntrySequenceIndex( tocNode )
  1906.     {
  1907.         if ( tocNode.parentNode == tocNode.ownerDocument.documentElement )
  1908.         {
  1909.             return 0;
  1910.         }
  1911.         
  1912.         var sequenceIndex = 0;
  1913.         
  1914.         var link = FMCGetAttribute( tocNode, "Link" );
  1915.             
  1916.         if ( link != null )
  1917.         {
  1918.             sequenceIndex++;
  1919.         }
  1920.  
  1921.         for ( var currNode = tocNode.previousSibling; currNode != null; currNode = currNode.previousSibling )
  1922.         {
  1923.             if ( currNode.nodeType != 1 ) { continue; }
  1924.             
  1925.             var descendantCount = FMCGetAttributeInt( currNode, "DescendantCount", 0 );
  1926.             
  1927.             sequenceIndex += descendantCount;
  1928.             
  1929.             var link = FMCGetAttribute( currNode, "Link" );
  1930.             
  1931.             if ( link != null )
  1932.             {
  1933.                 var linkUrl = new CMCUrl( link );
  1934.                 var ext = linkUrl.Extension.toLowerCase();
  1935.                 
  1936.                 if ( ext == "htm" || ext == "html" )
  1937.                 {
  1938.                     sequenceIndex++;
  1939.                 }
  1940.             }
  1941.         }
  1942.         
  1943.         return sequenceIndex + ComputeEntrySequenceIndex( tocNode.parentNode );
  1944.     }
  1945. }
  1946.  
  1947. //
  1948. //    End class CMCTocFile
  1949. //
  1950.  
  1951. /* -CatapultCompiler- -End- -Copy to CSH Javascript- */
  1952.